#include "IncomingPacket.hpp"
#include "MiscUtil.hpp"
#include "NetUtil.hpp"
#include "Packet.hpp"

static const int HEADER_SIZE = 8;

namespace kieper {
    // using std::ostream;
    IncomingPacket::IncomingPacket(char* buffer, unsigned int payloadSize) :
        buffer_(buffer), payloadSize_(payloadSize) {}
    IncomingPacket::~IncomingPacket() {}
    
    char* IncomingPacket::getBuffer() const {
        return buffer_;
    }

    char* IncomingPacket::getPayload() const {
        return buffer_ + HEADER_SIZE;
    }
    
    unsigned int IncomingPacket::getPayloadSize() {
        return payloadSize_;
    }
    
    uint32_t IncomingPacket::getPacketId() {
        return netutil::getFromNbo32(getBuffer(), 0);
    }

    uint16_t IncomingPacket::getDeviceId() {
        return netutil::getFromNbo16(getBuffer(), 2);
    }

    Packet::Type IncomingPacket::getType() {
        uint16_t messageInfo = netutil::getFromNbo16(getBuffer(), 3);
        if (!miscutil::getBitValue16(messageInfo, 15)) {
            return Packet::TYPE_CONTROL;
        } else {
            return Packet::TYPE_DATA;
        }
    }

    Packet::Delivery IncomingPacket::getDelivery() {
        uint16_t messageInfo = netutil::getFromNbo16(getBuffer(), 3);
        if (!miscutil::getBitValue16(messageInfo, 14)) {
            return Packet::DELIVERY_SYNC;
        } else {
            return Packet::DELIVERY_ASYNC;
        }
    }

    Packet::Scope IncomingPacket::getScope() {
        uint16_t messageInfo = netutil::getFromNbo16(getBuffer(), 3);
        if (!miscutil::getBitValue16(messageInfo, 13)) {
            return Packet::SCOPE_GLOBAL;
        } else {
            return Packet::SCOPE_DEVICE_SPECIFIC;
        }
    }

    Packet::Direction IncomingPacket::getDirection() {
        uint16_t messageInfo = netutil::getFromNbo16(getBuffer(), 3);
        if (!miscutil::getBitValue16(messageInfo, 12)) {
            return Packet::DIRECTION_REQUEST;
        } else {
            return Packet::DIRECTION_RESPONSE;
        }
    }

    uint16_t IncomingPacket::getMessageNumber() {
        uint16_t messageInfo = netutil::getFromNbo16(getBuffer(), 3);
        return messageInfo & 0x0FFF;
    }
}
